﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using thinger.AutomaticStoreMotionControlLib;
using thinger.AutomaticStoreMotionDAL;
using thinger.AutomaticStoreMotionModels;

namespace thinger.AutomaticStoreMotionPro
{
    public partial class FrmManual : Form
    {

        #region 构造函数
        public FrmManual()
        {
            InitializeComponent();
            this.Load += FrmManual_Load;
            this.FormClosing += FrmManual_FormClosing;
        }
        #endregion

        #region 属性和字段
        //界面刷新timer对象
        private System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();

        //运动控制单例模式
        private GTSMotionEx _gTSMotionEx = GTSMotionEx.GetInstance();

        //数字量输出的字段集合，存储信号名称及对应端口号
        private Dictionary<string, short> _currentOutDic = new Dictionary<string, short>();

        //运动控制的字段集合，存储轴点位及对应的位置数据
        private Dictionary<string, double> _currentMoveDic = new Dictionary<string, double>();
        #endregion

        #region 窗体加载
        private void FrmManual_Load(object sender, EventArgs e)
        {
            //初始化按钮事件及相关参数
            InitialEventAndParam<AdvancedParam>(headPanel1, _gTSMotionEx.AdvancedParam);
            InitialEventAndParam<AdvancedParam>(headPanel2, _gTSMotionEx.AdvancedParam);
            InitialEventAndParam<BasicParam>(headPanel3, _gTSMotionEx.BasicParam);
            InitialEventAndParam<BasicParam>(headPanel4, _gTSMotionEx.BasicParam);
            InitialEventAndParam<BasicParam>(headPanel5, _gTSMotionEx.BasicParam);

            //定时器初始化
            _timer.Interval = 200;
            _timer.Tick += _timer_Tick;
            _timer.Enabled = true;
        }

        //①绑定轴控和数字量输出事件，②轴控和数字量输出的字典数据初始化
        private void InitialEventAndParam<T>(HeadPanel headPanel, T obj)
        {
            foreach (Control ctrl in headPanel.Controls)
            {
                if (ctrl.Tag != null && ctrl.Tag.ToString().Length > 0)
                {
                    if (ctrl.Tag.ToString().Contains(';'))
                    {
                        string[] tags = ctrl.Tag.ToString().Split(';');
                        if (tags.Length == 2)
                        {
                            ctrl.Click += btn_OutCtrl_Click;
                            string propertyName = tags[0];
                            string value = GetObjectPropertyValue<T>(obj, propertyName);
                            if (value != null && value.Length > 0)
                            {
                                if (short.TryParse(value, out short res))
                                {
                                    if (_currentOutDic.ContainsKey(propertyName))
                                    {
                                        _currentOutDic[propertyName] = res;
                                    }
                                    else
                                    {
                                        _currentOutDic.Add(propertyName, res);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        ctrl.Click += btn_AxisCtrl_Click;
                        string propertyName = ctrl.Tag.ToString();
                        string value = GetObjectPropertyValue<T>(obj, propertyName);
                        if (value != null && value.Length > 0)
                        {
                            if (short.TryParse(value, out short res))
                            {
                                if (_currentMoveDic.ContainsKey(propertyName))
                                {
                                    _currentMoveDic[propertyName] = res;
                                }
                                else
                                {
                                    _currentMoveDic.Add(propertyName, res);
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 通过属性名称获取值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="propertyName">属性名</param>
        /// <returns>值</returns>
        private string GetObjectPropertyValue<T>(T obj, string propertyName)
        {
            try
            {
                Type type = typeof(T);
                PropertyInfo propertyInfo = type.GetProperty(propertyName);
                if (propertyInfo == null) return string.Empty;
                object val = propertyInfo.GetValue(obj);
                return val?.ToString();   // ?.  如果 val不为null，就执行ToString()
            }
            catch (Exception)
            {
                return null;
            }

        }

        #endregion

        #region 窗体关闭
        private void FrmManual_FormClosing(object sender, FormClosingEventArgs e)
        {
            _timer.Enabled = false;
        }
        #endregion

        #region 界面按钮外观刷新
        //界面按钮状态周期刷新事件
        private void _timer_Tick(object sender, EventArgs e)
        {
            UpdateState(headPanel1);
            UpdateState(headPanel2);
            UpdateState(headPanel3);
            UpdateState(headPanel4);
            UpdateState(headPanel5);
        }

        //界面按钮的刷新方法
        private void UpdateState(HeadPanel headPanel)
        {
            //获取输出状态值
            short status = _gTSMotionEx.GetOutput();
            //获取轴当前位置
            double posX = _gTSMotionEx.GetCmdPosX();
            double posY = _gTSMotionEx.GetCmdPosY();
            double posZ = _gTSMotionEx.GetCmdPosZ();

            foreach (Control control in headPanel.Controls)
            {
                if (control is Button btn)
                {
                    if (btn.Tag != null && btn.Tag.ToString().Length > 0)
                    {
                        string tag = btn.Tag.ToString();
                        if (tag.Contains(';'))
                        {
                            string[] tags = tag.Split(';');
                            if (tags.Length == 2)
                            {
                                string propertyName = tags[0];
                                if (_currentOutDic.ContainsKey(propertyName))
                                {
                                    int index = _currentOutDic[propertyName];
                                    bool val = (status & 1 << (index - 1)) != 0;

                                    SetButtonStyle(btn, tags[1] == "1" ? val : !val);
                                }
                            }
                        }
                        else
                        {
                            string propertyName = tag;
                            if (_currentMoveDic.ContainsKey(propertyName))
                            {
                                double value = _currentMoveDic[propertyName];
                                if (btn.Name.StartsWith("X"))
                                {
                                    SetButtonStyle(btn, Equal(posX, value));
                                }
                                else if (btn.Name.StartsWith("Y"))
                                {
                                    SetButtonStyle(btn, Equal(posY, value));
                                }
                                else if (btn.Name.StartsWith("Z"))
                                {
                                    SetButtonStyle(btn, Equal(posZ, value));
                                }
                            }
                        }
                    }
                }
            }
        }

        //按钮样式设定
        private void SetButtonStyle(Button button, bool isOpen)
        {
            button.BackColor = isOpen ? Color.LimeGreen : SystemColors.Control;
            button.ForeColor = isOpen ? Color.White : SystemColors.ControlText;
            button.FlatAppearance.MouseOverBackColor = isOpen ? Color.FromArgb(0, 195, 0) : Color.Gainsboro;
        }

        //轴定位数值比较
        private bool Equal(double value1, double value2, double offset = 0.2)
        {
            return Math.Abs(value1 - value2) < offset;
        }

        #endregion

        //*************界面操作相关事件触发**************
        #region 数字量输出控制
        /// <summary>
        /// 数字量输出控制
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_OutCtrl_Click(object sender, EventArgs e)
        {
            if (sender is Button btn)
            {
                if (btn.Tag != null && btn.Tag.ToString().Length > 0)
                {
                    if (btn.Name != "btnHandMode" && btn.Name != "btnAutoMode")
                    {
                        if (_gTSMotionEx.GetModeState())
                        {
                            HandModeVerify();
                            return;
                        }
                    }
                    string tag = btn.Tag.ToString();
                    if (tag.Contains(';'))
                    {
                        string[] tags = tag.Split(';');
                        if (tags.Length == 2)
                        {
                            string propertyName = tags[0];
                            if (_currentOutDic.ContainsKey(propertyName))
                            {
                                short index = _currentOutDic[propertyName];
                                var result = _gTSMotionEx.SetOutput(index, tags[1] == "1");
                                if (!result.IsSuccess)
                                {
                                    //操作失败
                                    new FrmConfirmSingleButton("操作失败", $"{btn.Text}操作失败：" + result.ErrorMsg).ShowDialog();
                                }
                            }
                        }
                    }

                }
            }
        }
        #endregion

        #region 轴绝对定位
        /// <summary>
        /// 轴绝对定位
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_AxisCtrl_Click(object sender, EventArgs e)
        {
            if (sender is Button btn)
            {
                btn.Enabled = false;
                if (btn.Tag != null && btn.Tag.ToString().Length > 0)
                {
                    if (btn.Name != "btnHandMode" && btn.Name != "btnAutoMode")
                    {
                        if (_gTSMotionEx.GetModeState())
                        {
                            HandModeVerify();
                            btn.Enabled = true;
                            return;
                        }
                    }

                    Task.Run(() =>   //线程中的btn能够和该方法的局部变量btn公用是因为：①每个线程都有自己的栈，②新创建一个线程时，它会在自己的栈上拷贝函数的局部变量
                    {
                        string tag = btn.Tag.ToString();
                        if (_currentMoveDic.ContainsKey(tag))
                        {
                            double value = _currentMoveDic[tag];
                            OperationResult result = OperationResult.CreateSuccessResut();
                            if (btn.Text.StartsWith("X"))
                            {
                                result = _gTSMotionEx.MoveXAbs(value);
                            }
                            else if (btn.Text.StartsWith("Y"))
                            {
                                result = _gTSMotionEx.MoveYAbs(value);
                            }
                            else if (btn.Text.StartsWith("Z"))
                            {
                                result = _gTSMotionEx.MoveZAbs(value);
                            }
                            if (result.IsSuccess)
                            {
                                //日记记录
                            }
                            else
                            {
                                this.Invoke(new Action(() =>
                                {
                                    new FrmConfirmSingleButton("轴绝对定位", $"{btn.Text}操作失败").ShowDialog(this);
                                }));
                            }
                        }
                    });
                }
                btn.Enabled = true;
            }
        }
        #endregion

        #region 轴回原点
        /// <summary>
        /// 轴回原点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAxisHome_Click(object sender, EventArgs e)
        {
            if (sender is Button btn)
            {
                btn.Enabled = false;
                if (btn.Tag != null && btn.Tag.ToString().Length > 0)
                {
                    if (btn.Name != "btnHandMode" && btn.Name != "btnAutoMode")
                    {
                        if (_gTSMotionEx.GetModeState())
                        {
                            HandModeVerify();
                            btn.Enabled = true;
                            return;
                        }
                    }
                    Task.Run(() =>
                    {
                        var result = _gTSMotionEx.HomeAxis(btn.Text);
                        if (result.IsSuccess)
                        {
                            //数据处理
                        }
                        else
                        {
                            this.Invoke(new Action(() =>
                            {
                                new FrmConfirmSingleButton("轴回原点", $"{btn.Text}操作失败").ShowDialog(this);
                            }));
                        }
                    });
                }
                btn.Enabled = true;
            }
        }
        #endregion

        #region 轴当前位置清零
        /// <summary>
        /// 轴当前位置清零
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAxisZero_Click(object sender, EventArgs e)
        {
            if (sender is Button btn)
            {
                btn.Enabled = false;
                if (btn.Tag != null && btn.Tag.ToString().Length > 0)
                {
                    if (btn.Name != "btnHandMode" && btn.Name != "btnAutoMode")
                    {
                        if (_gTSMotionEx.GetModeState())
                        {
                            HandModeVerify();
                            btn.Enabled = true;
                            return;
                        }
                    }
                    Task.Run(() =>
                    {
                        var result = _gTSMotionEx.ZeroPos(btn.Text);
                        if (result.IsSuccess)
                        {
                            //数据处理
                        }
                        else
                        {
                            this.Invoke(new Action(() =>
                            {
                                new FrmConfirmSingleButton("清零操作", $"{btn.Text}操作失败").ShowDialog(this);
                            }));
                        }
                    });
                }
                btn.Enabled = true;
            }
        }
        #endregion

        #region 一键回原点
        /// <summary>
        /// 一键回原点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAxisAllHome_Click(object sender, EventArgs e)
        {
            if (sender is Button btn)
            {
                btn.Enabled = false;
                if (btn.Tag != null && btn.Tag.ToString().Length > 0)
                {
                    if (btn.Name != "btnHandMode" && btn.Name != "btnAutoMode")
                    {
                        if (_gTSMotionEx.GetModeState())
                        {
                            HandModeVerify();
                            btn.Enabled = true;
                            return;
                        }
                    }

                    FrmConfirm frmConfirm = new FrmConfirm("一键回原点", "是否确认一键回原点", "确认", "取消");

                    if (frmConfirm.ShowDialog() == DialogResult.OK)
                    {
                        Task.Run(() =>
                        {
                            var result = _gTSMotionEx.ZeroPos(btn.Text);
                            if (result.IsSuccess)
                            {
                                //数据处理
                            }
                            else
                            {
                                this.Invoke(new Action(() =>
                                {
                                    new FrmConfirmSingleButton("清零操作", $"{btn.Text}操作失败").ShowDialog(this);
                                }));
                            }
                        });
                    }
                }
                btn.Enabled = true;
            }
        }
        #endregion

        #region 轴JOG运动
        //轴JOG运动触发
        private void btnAxisJOG_MouseDown(object sender, MouseEventArgs e)
        {
            if (sender is Button btn)
            {
                if (btn.Tag != null && btn.Tag.ToString().Length > 0)
                {
                    if (btn.Name != "btnHandMode" && btn.Name != "btnAutoMode")
                    {
                        if (_gTSMotionEx.GetModeState())
                        {
                            HandModeVerify();
                            return;
                        }
                        var result = _gTSMotionEx.JogMoveAxis(btn.Text);
                        if (result.IsSuccess)
                        {
                            //数据处理
                        }
                        else
                        {
                            new FrmConfirmSingleButton("轴点动", $"{btn.Text}操作失败").ShowDialog(this);
                        }
                    }
                }
            }
        }

        //轴运动停止
        private void btnAxisJOG_MouseUp(object sender, MouseEventArgs e)
        {
            if (sender is Button btn)
            {
                var result = _gTSMotionEx.StopAxis(btn.Text);

                if (result.IsSuccess)
                {
                    //数据处理
                }
                else
                {
                    new FrmConfirmSingleButton("轴点动", $"{btn.Text}操作失败").ShowDialog(this);
                }
            }
        }
        #endregion

        #region 手动模式通用的验证方法
        /// <summary>
        /// 手动模式通用的验证方法
        /// </summary>
        private void HandModeVerify()
        {
            DialogResult dialogResult = new FrmConfirm("模式切换", "是否切换至手动模式？", "确认切换", "取消切换").ShowDialog();
            if (dialogResult == DialogResult.OK)
            {
                var res = _gTSMotionEx.SetModeState(false);
                if (!res.IsSuccess)
                {
                    new FrmConfirmSingleButton("切换失败", "手动模式切换失败").ShowDialog();
                }
            }
        }
        #endregion

    }
}
